/*
 * Copyright (c)  2020,  DataPipeline
 * All rights reserved.
 *
 * Id:Beetl.java   2020-07-18 22:42 wanglijun
 */
package cn.datacare.orm.engine;

import cn.datacare.orm.loader.SQLLoader;
import org.beetl.core.AntlrProgramBuilder;
import org.beetl.core.Configuration;
import org.beetl.core.GroupTemplate;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;

import java.io.IOException;
import java.io.InputStream;
import java.nio.charset.Charset;
import java.util.Properties;

import static cn.datacare.orm.engine.EngineConfig.*;

/**
 * <p>
 * Title:
 * </p>
 * <p>
 * Description:
 * </p>
 * <p>
 * Copyright: Copyright (c) 2020
 * </p>
 * <p>
 * Company/Department: DataPipeline
 * </p>
 *
 * @author wanglijun
 * @version 1.0
 * @since 2020-07-18 22:42
 */
public class Beetl {
    /***
     * 日志
     */
    private static final Logger log = LoggerFactory.getLogger(Beetl.class);
    /**
     * 组模板
     */
    private final GroupTemplate groupTemplate;
    /**
     * 属性
     */
    private final Properties properties;

    /**
     * 私有化构造函数
     *
     * @param groupTemplate
     * @param properties
     */
    private Beetl(GroupTemplate groupTemplate, Properties properties) {
        this.groupTemplate = groupTemplate;
        this.properties = properties;
    }

    public static Builder builder() {
        return new Builder();
    }

    public GroupTemplate getGroupTemplate() {
        return groupTemplate;
    }

    public Properties getProperties() {
        return properties;
    }

    public boolean getOffsetStartZero(){
        return Boolean.parseBoolean(this.properties.getProperty(OFFSET_START_ZERO).trim());
    }

    /***
     * 构建模式
     */
    public static class Builder {



        /**
         * 组模板
         */
        private GroupTemplate groupTemplate;
        /**
         * 属性
         */
        private final Properties properties;

        /***
         * SQLLoader
         */
        private SQLLoader sqlLoader;

        protected Builder() {
            properties = new Properties();
        }

        /***
         *
         * @param properties
         * @return
         */
        public Builder properties(Properties properties) {
            this.properties.putAll(properties);
            return this;
        }

        /***
         * 构建SQLLoader
         * @param sqlLoader
         * @return Builder
         */
        public Builder sqlLoader(SQLLoader sqlLoader) {
            this.sqlLoader = sqlLoader;
            return this;
        }

        /***
         * 构建函数对象
         * @return Beetl
         */
        public Beetl build() {
            Properties properties = new Properties();
            try {
                //加载默认配置文件
                properties.putAll(this.loadDefaultConfig());
                //加载额外的配置文件
                properties.putAll(this.loadExtraConfig());
                //检查属性文件不为空
                properties.putAll(this.properties);
                //检查额外属
                this.groupTemplate = this.createGroupTemplate(properties);
                //初始化配置信息
                this.initConfig();

            } catch (Exception e) {
                throw new IllegalStateException(e);
            }
            return new Beetl(this.groupTemplate, properties);
        }


        protected void initConfig() {
            Boolean product = Boolean.valueOf(properties.getProperty(PRODUCT_MODE));
            String charset = this.properties.getProperty(CHARSET);
            if (charset == null || charset.length() == 0) {
                charset = Charset.defaultCharset().name();
            }
            this.sqlLoader.setCharset(charset);
            //对isBlank参数增加安全输出控制，如果不存在在，为空，返回true
            AntlrProgramBuilder.safeParameters.add(IS_BLANK);
            log.info("DataCare-ORM 运行在 product={},md charset={}", product, charset);
        }

        protected GroupTemplate createGroupTemplate(Properties properties) throws IOException {
            Boolean product = Boolean.valueOf(properties.getProperty(PRODUCT_MODE));
            StringSqlTemplateLoader resourceLoader = new StringSqlTemplateLoader(this.sqlLoader, !product);
            Configuration cfg = new Configuration(properties);
            GroupTemplate groupTemplate = new GroupTemplate(resourceLoader, cfg);
            return groupTemplate;
        }

        /**
         * 加载额外配置信息
         *
         * @return
         */
        protected Properties loadExtraConfig() {
            return this.loadConfig(EXT_CONFIG_FILE_NAME);
        }


        /***
         * 加载cfg自定义配置
         * @return Properties
         */
        protected Properties loadDefaultConfig() {
            return this.loadConfig(DEFAULT_CONFIG_FILE_NAME);
        }

        /**
         * 加载属性文件默认文件
         *
         * @param filePath 文件路径
         * @return Properties 属性值
         */
        private Properties loadConfig(String filePath) {
            log.info("DataCare-ORM加载属性配置文件：{}", filePath);
            Properties properties = null;
            try (InputStream ins = this.getClass().getResourceAsStream(filePath)) {
                if (ins != null) {
                    properties.load(ins);
                }
            } catch (IOException e) {
                log.error(e.getMessage(), e);
                throw new IllegalStateException("默认配置文件加载错:" + filePath);
            }
            return properties == null ? new Properties() : properties;
        }
    }
}
